#include "WE.h"
// #include "KeyboardHandle.h"
#include "MouseHandle.h"
#include <Core.h>

// 引用Windows头文件
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif // WIN32_LEAN_AND_MEAN
#include <windows.h>

#include <thread>

namespace WE
{
	class WindowsEvent
	{
	public:
		enum EVENT_STATE
		{
			EVENT_STATE_NOSING,
			EVENT_STATE_SING,
		};

	public:
		WindowsEvent() : mEvent(::CreateEventW(nullptr, TRUE, FALSE, nullptr))
		{
		}

		~WindowsEvent()
		{
			::CloseHandle(mEvent);
		}

		void WaitEvent()
		{
			::WaitForSingleObject(mEvent, INFINITE);
		}

		void Reset()
		{
			::ResetEvent(mEvent);
		}

		void Set()
		{
			::SetEvent(mEvent);
		}

	private:
		HANDLE mEvent;
	};

	enum FUNCTION_MODE
	{
		MODE_NONE,
		MODE_JUMP,
		MODE_WE,
		MODE_PINK,
	};

	static WindowsEvent we_signal{};
	static const int e_code = 18;
	static const int p_code = 25;
	static bool weSwitch = true;
	static FUNCTION_MODE gMode{MODE_NONE};
	static const double gThresholdTime = 0.25; // 单位s

	// static void WEProcess(const KeyBoardData *data)
	// {
	// 	const WPARAM w = data->wParam;

	// 	INFO("WE Process <%d><%d><%d>", data->vkCode, data->scanCode, data->dwExtraInfo);

	// 	const bool localLastWE = weSwitch;

	// 	if (data->dwExtraInfo == 0ull && data->vkCode == '4')
	// 	{
	// 		INFO("<{}><{}><{}>", data->vkCode, data->scanCode, data->dwExtraInfo);
	// 		weSwitch = (w == WM_KEYDOWN);
	// 	}

	// 	if (localLastWE == false)
	// 	{
	// 		we_signal.Set();
	// 	}
	// }

	static void SimulateKeyClick(const BYTE keyCode, const BYTE scanCode, const std::chrono::milliseconds time)
	{
		keybd_event(keyCode, scanCode, 0, 1);
		std::this_thread::sleep_for(time);
		keybd_event(keyCode, scanCode, KEYEVENTF_KEYUP, 1);
		std::this_thread::sleep_for(time);
	}

	static void WEProcessByMouse(const MouseData *data)
	{
		// using namespace std::chrono;
		// const WPARAM w = data->wParam;
		// static steady_clock::time_point localLastClickTime{};
		// static bool localWaitDBClick = false;

		// if (519 == w)
		// {
		// 	gMsState = MOUSE_KEY_STATE_DBCLICK;
		// 	we_signal.Set();
		// }
		// else if (520 == w)
		// {
		// 	gMsState = MOUSE_KEY_STATE_NONE;
		// }

		// INFO("WPARAM: %d, Data: %d\n",data->wParam,data->mouseData);

		// if (0x10000 == data->mouseData)
		// {
		// 	const steady_clock::time_point localCurrentTime = steady_clock::now();
		// 	const duration<double> localDurTime{localCurrentTime - localLastClickTime};

		// 	if (WM_XBUTTONDOWN == w)
		// 	{
		// 		if (localDurTime.count() < gThresholdTime && localWaitDBClick)
		// 		{
		// 			localWaitDBClick = false;
		// 			INFO("[DB%d]", data->mouseData);
		// 			gMsState = MOUSE_KEY_STATE_DBCLICK;
		// 		}
		// 		else
		// 		{
		// 			localWaitDBClick = true;
		// 			INFO("[Click%d]", data->mouseData);
		// 			gMsState = MOUSE_KEY_STATE_CLICK;
		// 		}

		// 		localLastClickTime = localCurrentTime;

		// 		we_signal.Set();
		// 	}
		// 	else
		// 	{
		// 		INFO("[UP%d]", data->mouseData);
		// 		gMsState = MOUSE_KEY_STATE_NONE;
		// 	}
		// }

		auto fnSetMode = [](FUNCTION_MODE mode) -> void
		{
			gMode = mode;
			we_signal.Set();
		};

		Mouse &ms = Mouse::GetInstance();

		if (data->curKey == MOUSE_KEY_XBUTTON_1 && ms.IsButtomDown(MOUSE_KEY_XBUTTON_1))
		{
			fnSetMode(MODE_WE);
			INFO("DB : %d\n", static_cast<int>(gMode));
		}
		else if (data->curKey == MOUSE_KEY_MBUTTON && data->dbclick == TRUE && ms.IsButtomDown(MOUSE_KEY_MBUTTON))
		{
			fnSetMode(MODE_PINK);
		}
		else if (data->curKey == MOUSE_KEY_MBUTTON && data->dbclick == FALSE && ms.IsButtomDown(MOUSE_KEY_MBUTTON))
		{
			fnSetMode(MODE_JUMP);
		}

		if (!ms.IsButtomDown(data->curKey))
		{
			gMode = MODE_NONE;
		}
	}

	DWORD WEMain(PVOID)
	{
		using namespace std::chrono;
		while (weSwitch)
		{
			we_signal.WaitEvent();
			while (weSwitch && (MODE_NONE != gMode))
			{
				switch (gMode)
				{
				case MODE_JUMP:
					SimulateKeyClick(VK_SPACE, 57, 10ms);
					INFO("JUMP");
					break;
				case MODE_WE:
					SimulateKeyClick('E', e_code, 10ms);
					INFO("WE");
					break;
				case MODE_PINK:
					SimulateKeyClick('P', p_code, 10ms);
					INFO("PINK");
					break;
				default:
					break;
				}
				// switch (gMsState)
				// {
				// case MOUSE_KEY_STATE_CLICK:
				// {
				// 	keybd_event('E', e_code, 0, 1);
				// 	std::this_thread::sleep_for(10ms);
				// 	keybd_event('E', e_code, KEYEVENTF_KEYUP, 1);
				// 	std::this_thread::sleep_for(10ms);
				// 	INFO("WE...\n");
				// 	break;
				// }
				// case MOUSE_KEY_STATE_DBCLICK:
				// {

				// 	keybd_event(VK_SPACE, 57, 0, 1);
				// 	std::this_thread::sleep_for(10ms);
				// 	keybd_event(VK_SPACE, 57, KEYEVENTF_KEYUP, 1);
				// 	std::this_thread::sleep_for(10ms);
				// 	INFO("JUMP\n");
				// 	break;
				// }
				// default:
				// 	break;
				// }
			}
			we_signal.Reset();
		}
		return 0x0;
	}

	void Start()
	{
		// Keyboard &kd = Keyboard::GetInstance();
		// kd.AddProc(WEProcess);

		Mouse &ms = Mouse::GetInstance();
		ms.AddProc(WEProcessByMouse);

		DWORD tsThreadID{};
		HANDLE tsThread = CreateThread(nullptr, 0x0, WEMain, nullptr, 0x0, &tsThreadID);
	}

	void Close()
	{
		weSwitch = false;
	}
}
